<template>
  <div class="hour-selector">
    <!-- 筛选选项 -->
    <div class="filter-tabs">
      <a-button class="tab-button" :class="{ active: activeTab === 'all' }" @click="selectTab('all')">全部时间</a-button>
      <a-button class="tab-button" :class="{ active: activeTab === 'workday' }" @click="selectTab('workday')">工作日</a-button>
      <a-button class="tab-button" :class="{ active: activeTab === 'weekend' }" @click="selectTab('weekend')">周末</a-button>
    </div>

    <!-- 时间表格 -->
    <div class="time-table-container" ref="tableContainer">
      <!-- 拖选框 - 只在拖动时显示 -->
      <div v-show="isSelecting && isDragging" class="selection-box" :style="selectionBoxStyle"></div>

      <table class="time-table" @mousedown.prevent @mouseleave="handleMouseLeave">
        <thead>
          <tr>
            <th class="day-label header-label" rowspan="2">星期/小时</th>
            <th :colspan="halfHourMode ? 24 : 12" class="time-period with-right-border">00:00~12:00</th>
            <th :colspan="halfHourMode ? 24 : 12" class="time-period">12:00~24:00</th>
          </tr>
          <tr>
            <!-- 小时刻度 -->
            <template v-if="!halfHourMode">
              <th v-for="hour in 24" :key="hour - 1" class="hour-cell">{{ hour - 1 }}</th>
            </template>
            <!-- 半小时刻度 - 小时标签跨两列 -->
            <template v-else>
              <th v-for="hour in 24" :key="hour - 1" class="hour-cell" colspan="2">
                {{ hour - 1 }}
              </th>
            </template>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(day, index) in days" :key="index">
            <td class="day-label" @click.prevent="selectDay(index + 1)">{{ day }}</td>
            <!-- 小时单元格 -->
            <template v-if="!halfHourMode">
              <td
                v-for="hour in 24"
                :key="`${index + 1}-${hour - 1}`"
                class="hour-cell"
                :class="{ selected: isSelected(index + 1, hour - 1, 0) }"
                @mousedown.prevent="startSelection(index + 1, hour - 1, 0, $event)"
                @mouseover="handleMouseOver(index + 1, hour - 1, 0, $event)"
                :data-day="index + 1"
                :data-hour="hour - 1"
                :data-minute="0"
              ></td>
            </template>
            <!-- 半小时单元格 -->
            <template v-else>
              <template v-for="hour in 24" :key="`${index + 1}-${hour - 1}`">
                <td
                  class="half-hour-cell"
                  :class="{ selected: isSelected(index + 1, hour - 1, 0) }"
                  @mousedown.prevent="startSelection(index + 1, hour - 1, 0, $event)"
                  @mouseover="handleMouseOver(index + 1, hour - 1, 0, $event)"
                  :data-day="index + 1"
                  :data-hour="hour - 1"
                  :data-minute="0"
                ></td>
                <td
                  class="half-hour-cell"
                  :class="{ selected: isSelected(index + 1, hour - 1, 30) }"
                  @mousedown.prevent="startSelection(index + 1, hour - 1, 30, $event)"
                  @mouseover="handleMouseOver(index + 1, hour - 1, 30, $event)"
                  :data-day="index + 1"
                  :data-hour="hour - 1"
                  :data-minute="30"
                ></td>
              </template>
            </template>
          </tr>
        </tbody>
      </table>
    </div>

    <!-- 已选择时间段 -->
    <div class="selected-time-slots">
      <div class="selected-label">已选择时间段 (可拖动鼠标选择时间段)</div>
      <a-button class="clear-button" @click="clearSelection">清空</a-button>
    </div>
    <!-- 已选时间段显示区域 -->
    <div class="selected-time-display" v-if="formattedTimeSlots.length">
      <div v-for="(slot, index) in formattedTimeSlots" :key="index" class="time-slot-item">
        {{ slot }}
      </div>
    </div>
    <div class="selected-time-display empty" v-else>
      <div class="time-slot-item empty">暂无选择时间段</div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted, watch } from "vue";

// 定义props
const props = defineProps({
  modelValue: {
    type: Object,
    default: () => ({
      1: [],
      2: [],
      3: [],
      4: [],
      5: [],
      6: [],
      7: [],
    }),
  },
  halfHourMode: {
    type: Boolean,
    default: false,
  },
});

// 定义emit
const emit = defineEmits(["update:modelValue"]);

// 响应式状态
const activeTab = ref("all");
const isSelecting = ref(false);
const isDragging = ref(false);
const selectionMode = ref(null); // 'add' 或 'remove'
const days = ref(["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]);
const tableContainer = ref(null);
const tableRect = ref(null); // 表格区域矩形
const cellsAreaRect = ref(null); // 单元格区域矩形

// 拖选位置数据
const selectionStart = ref(null);
const selectionEnd = ref(null);
const selectionStartPosition = ref(null);
const selectionEndPosition = ref(null);

// 拖选框样式 - 限制在单元格区域内
const selectionBoxStyle = computed(() => {
  if (!selectionStartPosition.value || !selectionEndPosition.value || !cellsAreaRect.value) return {};

  // 计算鼠标相对位置
  const { left, top, right, bottom } = cellsAreaRect.value;

  // 计算并限制在单元格区域内
  const x1 = Math.max(left, Math.min(right, selectionStartPosition.value.x));
  const y1 = Math.max(top, Math.min(bottom, selectionStartPosition.value.y));
  const x2 = Math.max(left, Math.min(right, selectionEndPosition.value.x));
  const y2 = Math.max(top, Math.min(bottom, selectionEndPosition.value.y));

  // 计算拖选框位置和尺寸
  return {
    left: `${Math.min(x1, x2) - tableRect.value.left}px`,
    top: `${Math.min(y1, y2) - tableRect.value.top}px`,
    width: `${Math.abs(x2 - x1)}px`,
    height: `${Math.abs(y2 - y1)}px`,
    borderColor: selectionMode.value === "add" ? "rgba(5, 180, 75, 0.8)" : "rgba(220, 53, 69, 0.8)",
    backgroundColor: selectionMode.value === "add" ? "rgba(5, 180, 75, 0.1)" : "rgba(220, 53, 69, 0.1)",
  };
});

// 创建选中状态数据结构
const selectedData = reactive({
  1: [],
  2: [],
  3: [],
  4: [],
  5: [],
  6: [],
  7: [],
});

// 初始化和事件设置
onMounted(() => {
  initData();
  updateTableRects();

  window.addEventListener("mouseup", endSelection);
  window.addEventListener("mousemove", handleMouseMove);
  window.addEventListener("resize", updateTableRects);
});

onUnmounted(() => {
  window.removeEventListener("mouseup", endSelection);
  window.removeEventListener("mousemove", handleMouseMove);
  window.removeEventListener("resize", updateTableRects);
});

// 初始化数据
const initData = () => {
  const slotCount = props.halfHourMode ? 48 : 24;

  // 初始化数据
  for (let day = 1; day <= 7; day++) {
    selectedData[day] = props.modelValue[day]?.length > 0 ? [...props.modelValue[day]] : Array(slotCount).fill(0);
  }
};

// 更新表格位置信息
const updateTableRects = () => {
  if (!tableContainer.value) return;

  // 获取表格容器位置
  tableRect.value = tableContainer.value.getBoundingClientRect();

  // 获取单元格区域位置
  const firstCell = tableContainer.value.querySelector("tbody td.hour-cell, tbody td.half-hour-cell");
  const lastRow = tableContainer.value.querySelector("tbody tr:last-child");
  const lastCell = lastRow?.querySelector("td.hour-cell:last-child, td.half-hour-cell:last-child");

  if (firstCell && lastCell) {
    const firstRect = firstCell.getBoundingClientRect();
    const lastRect = lastCell.getBoundingClientRect();

    cellsAreaRect.value = {
      left: firstRect.left,
      top: firstRect.top,
      right: lastRect.right,
      bottom: lastRect.bottom,
      width: lastRect.right - firstRect.left,
      height: lastRect.bottom - firstRect.top,
    };
  }
};

// 鼠标移动处理 - 更新拖动状态
const handleMouseMove = (event) => {
  if (!isSelecting.value) return;

  // 如果鼠标移动距离超过阈值，标记为拖动状态
  if (!isDragging.value) {
    const dx = Math.abs(event.clientX - selectionStartPosition.value.x);
    const dy = Math.abs(event.clientY - selectionStartPosition.value.y);

    // 如果移动了5像素以上，认为是拖动而非点击
    if (dx > 5 || dy > 5) {
      isDragging.value = true;
    }
  }

  // 更新鼠标位置
  selectionEndPosition.value = { x: event.clientX, y: event.clientY };

  // 不再每次都查找单元格，只在应用选择时进行完整计算
  // 这可以提高性能并避免框选中丢失单元格
};

// 开始选择 - 只记录意图，不改变状态
const startSelection = (day, hour, minute, event) => {
  updateTableRects();
  isSelecting.value = true;
  isDragging.value = false;

  // 记录起始信息
  selectionStart.value = { day, hour, minute };
  selectionEnd.value = { day, hour, minute };
  selectionStartPosition.value = { x: event.clientX, y: event.clientY };
  selectionEndPosition.value = { x: event.clientX, y: event.clientY };

  // 决定添加还是移除 - 注意这里只确定意图，不实际更改数据
  const slotIndex = getSlotIndex(hour, minute);
  selectionMode.value = selectedData[day][slotIndex] === 1 ? "remove" : "add";

  // 阻止默认行为，避免触发浏览器的原生点击视觉效果
  event.preventDefault();
  event.stopPropagation();
};

// 获取时间槽索引
const getSlotIndex = (hour, minute) => {
  return props.halfHourMode ? hour * 2 + (minute === 30 ? 1 : 0) : hour;
};

// 应用选择范围
const applySelection = () => {
  if (!selectionStart.value || !selectionEnd.value || !tableRect.value) return;

  // 获取表格中所有单元格
  const cells = Array.from(tableContainer.value.querySelectorAll("td.hour-cell, td.half-hour-cell")).filter((cell) => {
    // 只处理有数据属性的单元格（排除表头和星期标签）
    return cell.dataset.day && cell.dataset.hour !== undefined;
  });

  // 计算选择框的边界
  const selX1 = Math.min(selectionStartPosition.value.x, selectionEndPosition.value.x);
  const selY1 = Math.min(selectionStartPosition.value.y, selectionEndPosition.value.y);
  const selX2 = Math.max(selectionStartPosition.value.x, selectionEndPosition.value.x);
  const selY2 = Math.max(selectionStartPosition.value.y, selectionEndPosition.value.y);

  // 记录找到的单元格坐标
  const selectedCells = new Set();

  // 检查每个单元格是否在选择框内
  cells.forEach((cell) => {
    const cellRect = cell.getBoundingClientRect();

    // 检查单元格是否与选择框重叠
    const overlaps = !(cellRect.right < selX1 || cellRect.left > selX2 || cellRect.bottom < selY1 || cellRect.top > selY2);

    if (overlaps) {
      const day = parseInt(cell.dataset.day);
      const hour = parseInt(cell.dataset.hour);
      const minute = parseInt(cell.dataset.minute || 0);
      const key = `${day}-${hour}-${minute}`;
      selectedCells.add(key);
    }
  });

  // 应用选择到数据
  selectedCells.forEach((key) => {
    const [day, hour, minute] = key.split("-").map(Number);
    const slotIndex = getSlotIndex(hour, minute);
    selectedData[day][slotIndex] = selectionMode.value === "add" ? 1 : 0;
  });
};

// 结束选择 - 修复函数以调用applySelection
const endSelection = () => {
  if (!isSelecting.value) return;

  // 处理拖动操作
  if (isDragging.value) {
    // 应用框选区域
    applySelection();
  } else {
    // 单击处理 - 只在鼠标释放时应用
    const day = selectionStart.value.day;
    const hour = selectionStart.value.hour;
    const minute = selectionStart.value.minute;
    const slotIndex = getSlotIndex(hour, minute);

    // 根据选择模式应用更改
    selectedData[day][slotIndex] = selectionMode.value === "add" ? 1 : 0;
  }

  // 重置选择状态
  isSelecting.value = false;
  isDragging.value = false;

  // 发送变更事件
  emitChange();
};

// 检查是否选中 - 直接使用实际数据
const isSelected = (day, hour, minute) => {
  const index = getSlotIndex(hour, minute);
  return selectedData[day] && selectedData[day][index] === 1;
};

// 处理鼠标悬停
const handleMouseOver = (day, hour, minute, event) => {
  if (!isSelecting.value) return;

  selectionEnd.value = { day, hour, minute };
  selectionEndPosition.value = { x: event.clientX, y: event.clientY };
};

// 获取当前选择数据的方法
const getData = () => {
  const result = {};
  for (let day = 1; day <= 7; day++) {
    result[day] = [...selectedData[day]];
  }
  return result;
};

// 清空选择
const clearSelection = () => {
  const slotCount = props.halfHourMode ? 48 : 24;

  for (let day = 1; day <= 7; day++) {
    selectedData[day] = Array(slotCount).fill(0);
  }

  emitChange();
};

// 格式化时间段
const formattedTimeSlots = computed(() => {
  const result = [];
  const daysOfWeek = ["", "周一", "周二", "周三", "周四", "周五", "周六", "周日"];

  for (let day = 1; day <= 7; day++) {
    // 收集每天选中的时间段
    const dayRanges = [];
    const slots = selectedData[day];
    let startIndex = -1;

    // 寻找连续的时间段
    for (let i = 0; i <= slots.length; i++) {
      if (i < slots.length && slots[i] === 1) {
        if (startIndex === -1) startIndex = i;
      } else if (startIndex !== -1) {
        dayRanges.push(formatTimeRangeFromIndices(startIndex, i - 1));
        startIndex = -1;
      }
    }

    // 添加到结果
    if (dayRanges.length > 0) {
      result.push(`${daysOfWeek[day]}: ${dayRanges.join(", ")}`);
    }
  }

  return result;
});

// 从索引格式化时间范围
const formatTimeRangeFromIndices = (startIndex, endIndex) => {
  let startHour, startMinute, endHour, endMinute;

  if (props.halfHourMode) {
    startHour = Math.floor(startIndex / 2);
    startMinute = (startIndex % 2) * 30;
    endHour = Math.floor((endIndex + 1) / 2);
    endMinute = ((endIndex + 1) % 2) * 30;
    if (endMinute === 0 && endHour !== 0) endHour = endHour % 24;
  } else {
    startHour = startIndex;
    startMinute = 0;
    endHour = (endIndex + 1) % 24;
    endMinute = 0;
    if (endIndex === 23) endHour = 0;
  }

  return `${formatTime(startHour, startMinute)}-${formatTime(endHour, endMinute)}`;
};

// 格式化时间
const formatTime = (hour, minute) => {
  return `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`;
};

// 选择预设
const selectTab = (tab) => {
  activeTab.value = tab;
  const slotCount = props.halfHourMode ? 48 : 24;

  for (let day = 1; day <= 7; day++) {
    selectedData[day] = Array(slotCount).fill(
      tab === "all" || (tab === "workday" && day <= 5) || (tab === "weekend" && day >= 6) ? 1 : 0
    );
  }

  emitChange();
};

// 选择整天
const selectDay = (day) => {
  const allSelected = selectedData[day].every((value) => value === 1);
  selectedData[day] = Array(props.halfHourMode ? 48 : 24).fill(allSelected ? 0 : 1);

  emitChange();
};

// 发送变更事件
const emitChange = () => {
  const result = {};
  for (let day = 1; day <= 7; day++) {
    result[day] = [...selectedData[day]];
  }
  emit("update:modelValue", result);
};

// 处理鼠标离开表格 - 不需要特殊处理
const handleMouseLeave = () => {};

// 检查是否未选择任何时段
const hasNoTimeSelected = () => {
  for (let day = 1; day <= 7; day++) {
    if (selectedData[day].some((value) => value === 1)) {
      return false;
    }
  }
  return true;
};

// 暴露方法给父组件
defineExpose({
  getData,
  clearSelection, // 也暴露清空方法，方便外部调用
  selectTab, // 暴露选择预设方法
  hasNoTimeSelected,
});
</script>

<style scoped lang="less">
.hour-selector {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  -webkit-tap-highlight-color: transparent; // 移除移动设备上的点击高亮

  .filter-tabs {
    display: flex;
    padding-top: 10px;
    margin-bottom: 10px;

    .tab-button {
      padding: 5px 10px;
      margin-right: 5px;
    }
  }

  .time-table-container {
    position: relative;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    overflow: visible;
    user-select: none;

    // 拖选框样式
    .selection-box {
      position: absolute;
      border: 2px dashed rgba(5, 180, 75, 0.8);
      background-color: rgba(5, 180, 75, 0.1);
      pointer-events: none;
      z-index: 10;
      border-radius: 2px;
      box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
      transition: none;
      min-width: 5px; // 添加最小宽度，避免出现小点
      min-height: 5px; // 添加最小高度，避免出现小点
    }

    .time-table {
      width: 100%;
      border-collapse: collapse;
      table-layout: fixed;
      outline: none; // 移除表格可能的轮廓线

      .time-period {
        text-align: center;
        border-bottom: 1px solid #ebeef5;
        padding: 8px;
        font-weight: normal;
        color: #606266;

        &.with-right-border {
          border-right: 1px solid #ebeef5;
        }
      }

      .hour-cell,
      .half-hour-cell {
        position: relative;
        width: 30px;
        height: 32px;
        border: 1px solid #ebeef5;
        text-align: center;
        font-size: 12px;
        color: #606266;
        cursor: pointer;
        user-select: none;
        transition: none;
        outline: none;
        -webkit-tap-highlight-color: transparent;

        // 禁用所有可能导致视觉变化的状态
        &:active,
        &:hover,
        &:focus {
          // 重要：取消所有可能的视觉变化
          outline: none !important;
          appearance: none !important;
          -webkit-tap-highlight-color: transparent !important;
          background-image: none !important;
          background-color: inherit !important;
        }

        // 使用伪元素覆盖来处理选中状态
        &.selected::before {
          content: "";
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-color: #05b44b;
          pointer-events: none; // 确保事件穿透到底层
          z-index: 1;
        }
      }

      // 调整半小时单元格的宽度
      .half-hour-cell {
        width: 15px;
      }

      thead {
        .hour-cell,
        .half-hour-cell {
          background-color: #f5f7fa;
          font-weight: normal;
          cursor: default;

          &:hover,
          &:active {
            background-color: #f5f7fa !important;
            cursor: default;
          }
        }
      }

      .day-label {
        width: 90px;
        padding: 0 10px;
        text-align: center;
        border: 1px solid #ebeef5;
        font-weight: normal;
        background-color: #f5f7fa;
        color: #606266;
        cursor: pointer;

        &.header-label {
          cursor: default;

          &:hover {
            background-color: #f5f7fa !important;
          }
        }

        &:not(.header-label):hover {
          background-color: #e6f7ff;
        }
      }
    }
  }

  .selected-time-slots {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 10px;
    padding: 10px;
    background-color: #f5f7fa;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    color: #606266;
    font-size: 14px;
  }

  .selected-time-display {
    margin-top: 10px;
    padding: 10px;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    background-color: #fff;
    max-height: 150px;
    overflow-y: auto;

    &.empty {
      color: #909399;
      font-style: italic;
    }

    .time-slot-item {
      padding: 5px 0;
      border-bottom: 1px dashed #ebeef5;

      &:last-child {
        border-bottom: none;
      }

      &.empty {
        text-align: center;
      }
    }
  }
}
</style>
